home *** CD-ROM | disk | FTP | other *** search
/ BCI NET / BCI NET Dec 94.iso / archives / programming / c / gcc261ud-c.lha / gnu / ManualBrowser / DynamicHost.c next >
C/C++ Source or Header  |  1994-09-05  |  28KB  |  758 lines

  1. /************************************************************************/
  2. /*                                    */
  3. /*  Copyright (C) 1994  Christian Stieber                */
  4. /*                                    */
  5. /* This program is free software; you can redistribute it and/or modify    */
  6. /* it under the terms of the GNU General Public License as published by    */
  7. /* the Free Software Foundation; either version 2 of the License, or    */
  8. /* (at your option) any later version.                    */
  9. /*                                    */
  10. /* This program is distributed in the hope that it will be useful,    */
  11. /* but WITHOUT ANY WARRANTY; without even the implied warranty of    */
  12. /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    */
  13. /* GNU General Public License for more details.                */
  14. /*                                    */
  15. /* You should have received a copy of the GNU General Public License    */
  16. /* along with this program; if not, write to the Free Software        */
  17. /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.        */
  18. /*                                    */
  19. /************************************************************************/
  20. /*                                    */
  21. /* Author address:                            */
  22. /*   Christian Stieber                            */
  23. /*   Konradstraße 41                            */
  24. /*   D-85055 Ingolstadt                            */
  25. /*   (Germany)                                */
  26. /*   Phone: 0841-59896                            */
  27. /*                                    */
  28. /************************************************************************/
  29.  
  30. #ifndef V39
  31.    #define CreatePool LibCreatePool
  32.    #define DeletePool LibDeletePool
  33.    #define AllocPooled LibAllocPooled
  34.    #define FreePooled LibFreePooled
  35. #endif
  36.  
  37. #ifndef DOS_DOSEXTENS_H
  38. #include <dos/dosextens.h>
  39. #endif
  40.  
  41. #ifndef DOS_EXALL_H
  42. #include <dos/exall.h>
  43. #endif
  44.  
  45. #ifndef INTUITION_INTUITION_H
  46. #include <intuition/intuition.h>
  47. #endif
  48.  
  49. #ifndef LIBRARIES_AMIGAGUIDE_H
  50. #include <libraries/amigaguide.h>
  51. #endif
  52.  
  53. #ifndef WORKBENCH_STARTUP_H
  54. #include <workbench/startup.h>
  55. #endif
  56.  
  57. #ifndef WORKBENCH_WORKBENCH_H
  58. #include <workbench/workbench.h>
  59. #endif
  60.  
  61. #ifndef __GNUC__
  62.    #ifndef CLIB_EXEC_PROTOS_H
  63.    #include <clib/exec_protos.h>
  64.    #endif
  65.  
  66.    #ifndef CLIB_DOS_PROTOS_H
  67.    #include <clib/dos_protos.h>
  68.    #endif
  69.  
  70.    #ifndef CLIB_UTILITY_PROTOS_H
  71.    #include <clib/utility_protos.h>
  72.    #endif
  73.  
  74.    #ifndef CLIB_INTUITION_PROTOS_H
  75.    #include <clib/intuition_protos.h>
  76.    #endif
  77.  
  78.    #ifndef CLIB_ICON_PROTOS_H
  79.    #include <clib/icon_protos.h>
  80.    #endif
  81.  
  82.    #ifndef CLIB_AMIGAGUIDE_PROTOS_H
  83.    #include <clib/amigaguide_protos.h>
  84.    #endif
  85.  
  86.    #include <pragmas/exec_pragmas.h>
  87.    #include <pragmas/dos_pragmas.h>
  88.    #include <pragmas/intuition_pragmas.h>
  89.    #include <pragmas/utility_pragmas.h>
  90.    #include <pragmas/icon_pragmas.h>
  91.    #include <pragmas/amigaguide_pragmas.h>
  92. #endif
  93.  
  94. #include <string.h>
  95.  
  96. #include "Globals.h"
  97.  
  98. /***********************************************/
  99.  
  100. #ifdef __GNUC__
  101.  
  102. #include "Inlines.h"
  103.  
  104. #ifndef V39
  105.    APTR AllocPooled(APTR, ULONG);
  106.    void FreePooled(APTR, APTR, ULONG);
  107.    APTR CreatePool(ULONG, ULONG, ULONG);
  108.    void DeletePool(APTR);
  109. #endif
  110.  
  111. #endif   /* __GNUC__ */
  112.  
  113. /***********************************************/
  114.  
  115. #define MESSAGE_NAME    ".Message"
  116.  
  117. /***********************************************/
  118.  
  119. static char AboutText[]=
  120.    "\n"
  121.    "  This is the manual browser " PROGVERSION " (" PROGDATE "), " CPU " version\n"
  122. #ifdef V39
  123.    "  This executable was compiled for AmigaOS 3.0 (V39) and up.\n"
  124. #endif
  125.    "  Copyright © 1994 Christian Stieber\n"
  126.    "\n"
  127.    "\n"
  128.    "  This program is free software; you can redistribute it and/or modify\n"
  129.    "  it under the terms of the @{\x22GNU General Public License\x22 LINK COPYING/Main} as published by\n"
  130.    "  the Free Software Foundation; either version 2 of the License, or\n"
  131.    "  (at your option) any later version.\n"
  132.    "\n"
  133.    "  This program is distributed in the hope that it will be useful,\n"
  134.    "  but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
  135.    "  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
  136.    "  @{\x22GNU General Public License\x22 LINK COPYING/Main} for more details.\n"
  137.    "\n"
  138.    "  You should have received a copy of the @{\x22GNU General Public License\x22 LINK COPYING/Main}\n"
  139.    "  along with this program; if not, write to the Free Software\n"
  140.    "  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n"
  141.    "\n"
  142.    "\n"
  143.    "  Author: Christian Stieber\n"
  144.    "          Konradstraße 41\n"
  145.    "          D-85055 Ingolstadt\n"
  146.    "          (Germany)\n"
  147.    "\n"
  148.    "  Currently (1994) I'm a student and may reached at the following address:\n"
  149.    "\n"
  150.    "          Christian Stieber\n"
  151.    "          Seitzstraße 6, Zi. 306\n"
  152.    "          D-80538 München\n"
  153.    "          (Germany)\n"
  154.    "\n"
  155.    "          EMail: stieber@informatik.tu-muenchen.de\n"
  156.    "\n";
  157.  
  158. /***********************************************/
  159.  
  160. struct DirNode
  161.    {
  162.       struct DirNode *Next;
  163.       struct ActionNode *ActionNode;
  164.       char Name[1];
  165.    };
  166.  
  167. /***********************************************/
  168.  
  169. static struct DirNode *DirectoryList;
  170. static struct DirNode *FileList;
  171. static char *NodeData;
  172. static ULONG NodeLength;
  173.  
  174. static char *MessageText;
  175. static int MessageLength;
  176.  
  177. #ifdef __GNUC__
  178.    static struct FileInfoBlock FileInfoBlock __attribute__((aligned(4)));
  179. #else
  180.    static struct FileInfoBlock __aligned FileInfoBlock;
  181. #endif
  182.  
  183. /***********************************************/
  184.  
  185. static void InsertDirNode(struct DirNode *DirNode, struct DirNode **DirList)
  186.  
  187. {
  188.    if (!*DirList)
  189.       {
  190.          *DirList=DirNode;
  191.          DirNode->Next=NULL;
  192.       }
  193.    else
  194.       {
  195.          struct DirNode *Prev, *Current;
  196.  
  197.          Prev=(struct DirNode *)DirList;
  198.          Current=Prev->Next;
  199.          while (Current && (Stricmp(Current->Name,DirNode->Name)<0))
  200.             {
  201.                Prev=Current;
  202.                Current=Current->Next;
  203.             }
  204.          Prev->Next=DirNode;
  205.          DirNode->Next=Current;
  206.       }
  207. }
  208.  
  209. /***********************************************/
  210.  
  211. static void FreeDirNodes(struct DirNode **DirList)
  212.  
  213. {
  214.    while (*DirList)
  215.       {
  216.          struct DirNode *Next;
  217.          Next=(*DirList)->Next;
  218.          FreePooled(MemoryPool,*DirList,sizeof(struct DirNode)+strlen((*DirList)->Name));
  219.          *DirList=Next;
  220.       }
  221. }
  222.  
  223. /***********************************************/
  224.  
  225. static struct ActionNode *FindActionNode(char *Filename)
  226.  
  227. {
  228.    struct ActionNode *ActionNode;
  229.  
  230.    for (ActionNode=ActionList; ActionNode; ActionNode=ActionNode->Next)
  231.       {
  232.          if (MatchPatternNoCase(ActionNode->Pattern,Filename))
  233.             {
  234.                break;
  235.             }
  236.       }
  237.    return ActionNode;
  238. }
  239.  
  240. /***********************************************/
  241.  
  242. static int Message;
  243.  
  244. #define BUFFER_SIZE (4*1024)
  245.  
  246. static long ReadDir(BPTR DirLock)
  247.  
  248. {
  249.    struct ExAllControl *ExAllControl;
  250.    long DosError;
  251.  
  252.    DosError=0;
  253.    Message=FALSE;
  254.    if ((ExAllControl=AllocDosObject(DOS_EXALLCONTROL,NULL)))
  255.       {
  256.          struct ExAllData *Buffer;
  257.          if ((Buffer=AllocPooled(MemoryPool,BUFFER_SIZE)))
  258.             {
  259.                int more;
  260.                ExAllControl->eac_LastKey=0;
  261.                ExAllControl->eac_MatchString=NULL;
  262.                ExAllControl->eac_MatchFunc=NULL;
  263.                do
  264.                   {
  265.                      more=ExAll(DirLock,Buffer,BUFFER_SIZE,ED_TYPE,ExAllControl);
  266.                      if ((!more) && (IoErr()!=ERROR_NO_MORE_ENTRIES))
  267.                         {
  268.                            DosError=IoErr();
  269.                         }
  270.                      else
  271.                         {
  272.                            if (ExAllControl->eac_Entries)
  273.                               {
  274.                                  struct ExAllData *ExAllData;
  275.                                  ExAllData=Buffer;
  276.                                  do
  277.                                     {
  278.                                        if (Stricmp(ExAllData->ed_Name,MESSAGE_NAME))
  279.                                           {
  280.                                              struct ActionNode *ActionNode;
  281.                                              ActionNode=FindActionNode(ExAllData->ed_Name);
  282.                                              if (!ActionNode || Stricmp(ActionNode->Action,"IGNORE"))
  283.                                                 {
  284.                                                    struct DirNode *DirNode;
  285.                                                    if (ActionNode && !Stricmp(ActionNode->Action,"DEFAULT"))
  286.                                                       {
  287.                                                          ActionNode=NULL;
  288.                                                       }
  289.                                                    if ((DirNode=AllocPooled(MemoryPool,sizeof(struct DirNode)+strlen(ExAllData->ed_Name))))
  290.                                                       {
  291.                                                          DirNode->ActionNode=ActionNode;
  292.                                                          strcpy(DirNode->Name,ExAllData->ed_Name);
  293.                                                          if (ExAllData->ed_Type==ST_SOFTLINK)
  294.                                                             {
  295.                                                                BPTR LinkLock;
  296.                                                                BPTR OldCurrDir;
  297.                                                                OldCurrDir=CurrentDir(DirLock);
  298.                                                                if ((LinkLock=Lock(ExAllData->ed_Name,SHARED_LOCK)))
  299.                                                                   {
  300.                                                                      if (Examine(LinkLock,&FileInfoBlock))
  301.                                                                         {
  302.                                                                            InsertDirNode(DirNode,FileInfoBlock.fib_DirEntryType>=0 ? &DirectoryList : &FileList);
  303.                                                                         }
  304.                                                                      UnLock(LinkLock);
  305.                                                                   }
  306.                                                                CurrentDir(OldCurrDir);
  307.                                                             }
  308.                                                          else
  309.                                                             {
  310.                                                                InsertDirNode(DirNode,ExAllData->ed_Type>=0 ? &DirectoryList : &FileList);
  311.                                                             }
  312.                                                       }
  313.                                                    else
  314.                                                       {
  315.                                                          DosError=IoErr();
  316.                                                       }
  317.                                                 }
  318.                                           }
  319.                                        else
  320.                                           {
  321.                                              Message=TRUE;
  322.                                           }
  323.                                        ExAllData=ExAllData->ed_Next;
  324.                                     }
  325.                                  while (!DosError && ExAllData);
  326.                               }
  327.                         }
  328.                   }
  329.                while (!DosError && more);
  330.                if (more)
  331.                   {
  332. #ifdef V39
  333.                      ExAllEnd(DirLock,Buffer,BUFFER_SIZE,ED_TYPE,ExAllControl);
  334. #else
  335.                      while (ExAll(DirLock,Buffer,BUFFER_SIZE,ED_TYPE,ExAllControl)) ;
  336. #endif
  337.                   }
  338.                if (DosError)
  339.                   {
  340.                      FreeDirNodes(&DirectoryList);
  341.                      FreeDirNodes(&FileList);
  342.                   }
  343.                FreePooled(MemoryPool,Buffer,BUFFER_SIZE);
  344.             }
  345.          else
  346.             {
  347.                DosError=IoErr();
  348.             }
  349.          FreeDosObject(DOS_EXALLCONTROL,ExAllControl);
  350.       }
  351.    else
  352.       {
  353.          DosError=IoErr();
  354.       }
  355.    return DosError;
  356. }
  357.  
  358. #undef BUFFER_SIZE
  359.  
  360. /***********************************************/
  361.  
  362. static char *NodeDataTmp;
  363.  
  364. static int PrintNodeText(char *Text)
  365.  
  366. {
  367.    if (NodeDataTmp)
  368.       {
  369.          NodeDataTmp=Stpcpy(NodeDataTmp,Text);
  370.       }
  371.    return strlen(Text);
  372. }
  373.  
  374. /***********************************************/
  375.  
  376. static int PrintDir(char *ThisDir, char *PathName)
  377.  
  378. {
  379.    int Length;
  380.    struct DirNode *Current;
  381.    short ColWidth, Columns;
  382.    short MaxLength;
  383.    short Column;
  384.  
  385.    /* Max. length of the buttons */
  386.    MaxLength=0;
  387.    for (Current=DirectoryList; Current; Current=Current->Next)
  388.       {
  389.          Length=strlen(Current->Name)+1;
  390.          if (Length>MaxLength) MaxLength=Length;
  391.       }
  392.    for (Current=FileList; Current; Current=Current->Next)
  393.       {
  394.          Length=strlen(Current->Name);
  395.          if (Length>MaxLength) MaxLength=Length;
  396.       }
  397.    if (AmigaGuideBase->lib_Version>=39) MaxLength++;
  398.  
  399.    Columns=LineLength/(MaxLength+1);
  400.    ColWidth=LineLength/Columns;
  401.    if (AmigaGuideBase->lib_Version>=39) ColWidth--;
  402.  
  403.    Length=0;
  404.  
  405.    Column=0;
  406.    for (Current=DirectoryList; Current; Current=Current->Next)
  407.       {
  408.          int CurWidth;
  409.          CurWidth=0;
  410.          Length+=PrintNodeText("@{\x22");
  411.          CurWidth+=PrintNodeText(Current->Name);
  412.          CurWidth+=PrintNodeText("/");
  413.          Length+=PrintNodeText("\x22 LINK \x22");
  414.          if (*ThisDir)
  415.             {
  416.                Length+=PrintNodeText(ThisDir);
  417.                Length+=PrintNodeText("/");
  418.             }
  419.          Length+=PrintNodeText(Current->Name);
  420.          Length+=PrintNodeText("\x22}");
  421.          Column++;
  422.          if (Column>=Columns)
  423.             {
  424.                Length+=PrintNodeText("\n");
  425.                Column=0;
  426.             }
  427.          else
  428.             {
  429.                while (CurWidth<ColWidth) CurWidth+=PrintNodeText(" ");
  430.             }
  431.          Length+=CurWidth;
  432.       }
  433.    if (Column)
  434.       {
  435.          Length+=PrintNodeText("\n");
  436.       }
  437.  
  438.    if (DirectoryList && FileList)
  439.       {
  440.          Length+=PrintNodeText("\n\n");
  441.       }
  442.  
  443.    Column=0;
  444.    for (Current=FileList; Current; Current=Current->Next)
  445.       {
  446.          int CurWidth;
  447.          CurWidth=0;
  448.          Length+=PrintNodeText("@{\x22");
  449.          CurWidth+=PrintNodeText(Current->Name);
  450.          Length+=PrintNodeText("\x22 ");
  451.          if (Current->ActionNode)
  452.             {
  453.                char *t;
  454.                char x[4];
  455.  
  456.                x[1]='\0';
  457.                for (t=Current->ActionNode->Action; *t; t++)
  458.                   {
  459.                      if (*t=='%')
  460.                         {
  461.                            switch(*(t+1))
  462.                               {
  463.                                  case '%': Length+=PrintNodeText("%");
  464.                                            t++;
  465.                                            break;
  466.  
  467.                                  case 'p': Length+=PrintNodeText(PathName);
  468.                                            t++;
  469.                                            break;
  470.  
  471.                                  case 'f': Length+=PrintNodeText(Current->Name);
  472.                                            t++;
  473.                                            break;
  474.  
  475.                                  case 'F': {
  476.                                               char *u, *v;
  477.                                               v=NULL;
  478.                                               for (u=Current->Name; *u; u++)
  479.                                                  {
  480.                                                     if (*u=='.') v=u;
  481.                                                  }
  482.                                               if (!v) v=u;
  483.                                               for (u=Current->Name; u!=v; u++)
  484.                                                  {
  485.                                                     x[0]=*u;
  486.                                                     Length+=PrintNodeText(x);
  487.                                                  }
  488.                                            }
  489.                                            t++;
  490.                                            break;
  491.  
  492.                                  default:  x[0]=*t;
  493.                                            Length+=PrintNodeText(x);
  494.                                            break;
  495.                               }
  496.                         }
  497.                      else
  498.                         {
  499.                            x[0]=*t;
  500.                            Length+=PrintNodeText(x);
  501.                         }
  502.                   }
  503.             }
  504.          else
  505.             {
  506.                Length+=PrintNodeText("LINK \x22");
  507.                if (*ThisDir)
  508.                   {
  509.                      Length+=PrintNodeText(ThisDir);
  510.                      Length+=PrintNodeText("/");
  511.                   }
  512.                Length+=PrintNodeText(Current->Name);
  513.                Length+=PrintNodeText("/Main");
  514.                Length+=PrintNodeText("\x22");
  515.             }
  516.          Length+=PrintNodeText("}");
  517.          Column++;
  518.          if (Column>=Columns)
  519.             {
  520.                Length+=PrintNodeText("\n");
  521.                Column=0;
  522.             }
  523.          else
  524.             {
  525.                while (CurWidth<ColWidth) CurWidth+=PrintNodeText(" ");
  526.             }
  527.          Length+=CurWidth;
  528.       }
  529.    if (Column)
  530.       {
  531.          Length+=PrintNodeText("\n");
  532.       }
  533.  
  534.    return Length;
  535. }
  536.  
  537. /***********************************************/
  538.  
  539. static int PrintMessage(void)
  540.  
  541. {
  542.    if (MessageText)
  543.       {
  544.          int Length;
  545.          Length=PrintNodeText(MessageText);
  546.          Length+=PrintNodeText("\n");
  547.          return Length;
  548.       }
  549.    else
  550.       {
  551.          return 0;
  552.       }
  553. }
  554.  
  555. /***********************************************/
  556.  
  557. static void ReadMessage(BPTR DirLock)
  558.  
  559. {
  560.    BPTR FileHandle;
  561.    BPTR OldCurrDir;
  562.  
  563.    OldCurrDir=CurrentDir(DirLock);
  564.    if ((FileHandle=Open(MESSAGE_NAME,MODE_OLDFILE)))
  565.       {
  566.          if (ExamineFH(FileHandle,&FileInfoBlock))
  567.             {
  568.                MessageLength=FileInfoBlock.fib_Size+1;
  569.                if ((MessageText=AllocPooled(MemoryPool,MessageLength)))
  570.                   {
  571.                      Read(FileHandle,MessageText,MessageLength-1);
  572.                      MessageText[MessageLength-1]='\0';
  573.                   }
  574.             }
  575.          Close(FileHandle);
  576.       }
  577.    CurrentDir(OldCurrDir);
  578. }
  579.  
  580. /***********************************************/
  581.  
  582. #ifdef __GNUC__
  583. ULONG AmigaGuideHostDispatcher(Msg Message)
  584. #else
  585. ULONG __saveds __asm AmigaGuideHostDispatcher(register __a1 Msg Message)
  586. #endif
  587.  
  588. {
  589.    switch(Message->MethodID)
  590.       {
  591.          case HM_FINDNODE:  {
  592.                                char *Name;
  593.  
  594.                                Name=((struct opFindHost *)Message)->ofh_Node;
  595.                                while (!Strnicmp(Name,DatabaseName,strlen(DatabaseName)))
  596.                                   {
  597.                                      Name+=strlen(DatabaseName)+1;
  598.                                   }
  599.  
  600.                                ((struct opFindHost *)Message)->ofh_Next=((struct opFindHost *)Message)->ofh_Prev=((struct opFindHost *)Message)->ofh_Node;
  601.  
  602.                                if (!Stricmp("main",Name))
  603.                                   {
  604.                                      ((struct opFindHost *)Message)->ofh_Title="Manual browser " PROGVERSION;
  605.                                   }
  606.                                else if (!strcmp("AbOuT",Name))
  607.                                   {
  608.                                      ((struct opFindHost *)Message)->ofh_Title="About the manual browser";
  609.                                   }
  610.                                else
  611.                                   {
  612.                                      BPTR OldCurrDir;
  613.                                      BPTR TestLock;
  614.  
  615.                                      OldCurrDir=CurrentDir(ManDir);
  616.                                      if ((TestLock=Lock(Name,SHARED_LOCK)))
  617.                                         {
  618.                                            UnLock(TestLock);
  619.                                         }
  620.                                      CurrentDir(OldCurrDir);
  621.                                      if (!TestLock) return FALSE;
  622.                                      ((struct opFindHost *)Message)->ofh_Title=Name;
  623.                                      ((struct opFindHost *)Message)->ofh_TOC="main";
  624.                                   }
  625.                                return TRUE;
  626.                             }
  627.                             break;
  628.  
  629.          case HM_OPENNODE:  {
  630.                                BPTR DirLock;
  631.                                BPTR OldCurrDir;
  632.                                char *Name;
  633.                                int Main;
  634.                                long DosError;
  635.  
  636.                                DosError=0;
  637.                                ((struct opNodeIO *)Message)->onm_Flags=HTNF_CLEAN;
  638.                                ((struct opNodeIO *)Message)->onm_FileName=NULL;
  639.                                Name=((struct opNodeIO *)Message)->onm_Node;
  640.                                while (!Strnicmp(Name,DatabaseName,strlen(DatabaseName)))
  641.                                   {
  642.                                      Name+=strlen(DatabaseName)+1;
  643.                                   }
  644.  
  645.                                if ((Main=!Stricmp("main",Name)))
  646.                                   {
  647.                                      Name+=4;
  648.                                   }
  649.                                else if (!strcmp("AbOuT",Name))
  650.                                   {
  651.                                      ((struct opNodeIO *)Message)->onm_DocBuffer=AboutText;
  652.                                      ((struct opNodeIO *)Message)->onm_BuffLen=sizeof(AboutText)-1;
  653.                                      return TRUE;
  654.                                   }
  655.  
  656.                                OldCurrDir=CurrentDir(ManDir);
  657.                                if ((DirLock=Lock(Name,SHARED_LOCK)))
  658.                                   {
  659.                                      char *DirName;
  660.                                      int DirNameLength;
  661.  
  662.                                      DirNameLength=256;
  663.                                      do
  664.                                         {
  665.                                            if ((DirName=AllocPooled(MemoryPool,DirNameLength)))
  666.                                               {
  667.                                                  if (NameFromLock(DirLock,DirName,DirNameLength))
  668.                                                     {
  669.                                                        break;
  670.                                                     }
  671.                                                  if (IoErr()!=ERROR_LINE_TOO_LONG)
  672.                                                     {
  673.                                                        DosError=IoErr();
  674.                                                     }
  675.                                                  FreePooled(MemoryPool,DirName,DirNameLength);
  676.                                                  DirName=NULL;
  677.                                                  DirNameLength+=256;
  678.                                               }
  679.                                            else
  680.                                               {
  681.                                                  DosError=IoErr();
  682.                                               }
  683.                                         }
  684.                                      while (!DosError);
  685.                                      if (!DosError && !(DosError=ReadDir(DirLock)))
  686.                                         {
  687.                                            NodeDataTmp=NULL;
  688.                                            NodeLength=0;
  689.                                            if (Message)
  690.                                               {
  691.                                                  ReadMessage(DirLock);
  692.                                                  NodeLength+=PrintMessage();
  693.                                               }
  694.                                            NodeLength+=PrintDir(Name,DirName);
  695.                                            if (Main)
  696.                                               {
  697.                                                  NodeLength+=PrintNodeText("\n\n"
  698.                                                                            "@{\x22""About the manual browser\x22 LINK \x22""AbOuT\x22}\n");
  699.                                               }
  700.  
  701.                                            if ((NodeData=AllocPooled(MemoryPool,NodeLength+1)))
  702.                                               {
  703.                                                  NodeDataTmp=NodeData;
  704.                                                  PrintMessage();
  705.                                                  PrintDir(Name,DirName);
  706.                                                  if (Main)
  707.                                                     {
  708.                                                        PrintNodeText("\n\n"
  709.                                                                      "@{\x22""About the manual browser\x22 LINK \x22""AbOuT\x22}\n");
  710.                                                     }
  711.                                                  ((struct opNodeIO *)Message)->onm_DocBuffer=NodeData;
  712.                                                  ((struct opNodeIO *)Message)->onm_BuffLen=NodeLength;
  713.                                                  UnLock(OldCurrDir);
  714.                                                  OldCurrDir=DirLock;
  715.                                               }
  716.                                            else
  717.                                               {
  718.                                                  DosError=IoErr();
  719.                                               }
  720.                                            if (MessageText)
  721.                                               {
  722.                                                  FreePooled(MemoryPool,MessageText,MessageLength);
  723.                                                  MessageText=NULL;
  724.                                               }
  725.                                         }
  726.                                      if (!NodeData) UnLock(DirLock);
  727.                                      if (DirName)
  728.                                         {
  729.                                            FreePooled(MemoryPool,DirName,DirNameLength);
  730.                                         }
  731.                                   }
  732.                                else
  733.                                   {
  734.                                      DosError=IoErr();
  735.                                   }
  736.                                CurrentDir(OldCurrDir);
  737.                                if (DosError)
  738.                                   {
  739.                                      static char FaultString[84];
  740.                                      ((struct opNodeIO *)Message)->onm_DocBuffer=FaultString;
  741.                                      ((struct opNodeIO *)Message)->onm_BuffLen=Fault(DosError,NULL,FaultString,sizeof(FaultString));
  742.                                   }
  743.                                return TRUE;
  744.                             }
  745.                             break;
  746.  
  747.          case HM_CLOSENODE: {
  748.                                if (NodeData) FreePooled(MemoryPool,NodeData,NodeLength+1);
  749.                                NodeData=NULL;
  750.                                FreeDirNodes(&DirectoryList);
  751.                                FreeDirNodes(&FileList);
  752.                                return TRUE;
  753.                             }
  754.                             break;
  755.       }
  756.    return FALSE;
  757. }
  758.